<?php
// +----------------------------
// | Created by PhpStorm
// +----------------------------
// | Author: YnnSon
// +----------------------------
namespace app\api\service;

use app\lib\enum\ScopeEnum;
use app\lib\exception\ForbiddenException;
use app\lib\exception\TokenException;
use think\Cache;
use think\Config;
use think\Exception;
use think\Request;

/**
 * Token类
 * Class Token
 * @package app\api\service
 */
class Token
{
    /**
     * @Desc 生成令牌, 由32位随机字符串+时间戳+salt的md5值组成
     * @return string Token
     */
    protected static function generateToken()
    {
        $str = randomChar(32);
        $timestamp = Request::instance()->server('REQUEST_TIME');
        $salt = Config::get('setting.token_salt');
        return md5($str . $timestamp . $salt);
    }

    /**
     * @Desc 验证Token有效性
     * @param string $token 客户端传来的token
     * @return array ['isValid' => true|false]
     */
    public static function verifyTokenValidity($token)
    {
        $result = Cache::get($token) ? true : false;
        return ['isValid' => $result];
    }

    /**
     * @value openid+uid+scope
     * @desc  通过token获取缓存值
     * @param string $key 缓存字段名
     * @return string 缓存字段值
     */
    public static function getCacheValueByToken($key)
    {
        // 1.客户端通过header传递token给后端
        $token = Request::instance()->header('token');
        // 2.根据Token到缓存中获取值
        $cacheValue = Cache::get($token);
        if (!$cacheValue) {
            throw new TokenException();
        }
        if (!is_array($cacheValue)) {
            $cacheValue = json_decode($cacheValue, true);
        }
        if (!array_key_exists($key, $cacheValue)) {
            throw new Exception('尝试获取的token变量不存在');
        }
        return $cacheValue[$key];
    }

    /**
     * @Desc 从缓存中获取uid
     * @return string uid
     */
    public static function getUidFromCache()
    {
        return self::getCacheValueByToken('uid');
    }

    /**
     * @Desc 从缓存中获取scope
     * @return string scope
     */
    public static function getScopeFromCache()
    {
        return self::getCacheValueByToken('scope');
    }

    /**
     * @Desc 从缓存中获取openid
     * @return string openid
     */
    public static function getOpenidFromCache()
    {
        return self::getCacheValueByToken('openid');
    }

    /**
     * @Desc 从缓存中获取session_key
     * @return string session_key
     */
    public static function getSessionKeyFromCache()
    {
        return self::getCacheValueByToken('session_key');
    }

    /**
     * @Desc 检查是否是当前用户操作
     * @param int $checkedUid 要检查的UID
     * @return bool true|false
     */
    public static function checkUid($checkedUid)
    {
        $result = true;
        if (!$checkedUid) {
            throw new Exception('必须传入一个Uid');
        }
        $currentUid = self::getUidFromCache();
        if ($currentUid != $checkedUid) {
            $result = false;
        }
        return $result;
    }

    /**
     * @Desc 检查是否是当前用户操作
     * @param int $checkedOpenid 要检查的Openid
     * @return bool true|false
     */
    public static function checkOpenid($checkedOpenid)
    {
        $result = true;
        if (!$checkedOpenid) {
            throw new Exception('必须传入一个Uid');
        }
        $currentOpenid = self::getOpenidFromCache();
        if ($currentOpenid != $checkedOpenid) {
            $result = false;
        }
        return $result;
    }

    /**
     * @Desc 获取主要权限
     * @return bool true
     */
    public static function needPrimaryScope()
    {
        $scope = self::getScopeFromCache();
        if (!$scope) {
            throw new TokenException();
        }
        if ($scope < ScopeEnum::USER) {
            throw new ForbiddenException();
        }
        return true;
    }

    /**
     * @Desc 获取用户权限
     * @return bool true
     */
    public static function needUserScope()
    {
        $scope = self::getScopeFromCache();
        if (!$scope) {
            throw new TokenException();
        }
        if (ScopeEnum::USER != $scope) {
            throw new ForbiddenException();
        }
        return true;
    }

    /**
     * @Desc 获取超级权限
     * @return bool true
     */
    public static function needSuperScope()
    {
        $scope = self::getScopeFromCache();
        if (!$scope) {
            throw new TokenException();
        }
        if (ScopeEnum::SUPER != $scope) {
            throw new ForbiddenException();
        }
        return true;
    }
}